package com.study.myThreadLocal;

/**
 * @description:
 * @author: 汤凌宇
 * @time: 2021/6/24 22:00
 */
public class MyThreadLocal extends ThreadLocal<MyCounter> {

    /**
     * 需要注意这个例子中的两个非常关键的点：
     * MyCounter以及MyThreadLocal必须放到web应用的路径中,并被Webapp Classloader加载
     * ThreadLocal类一定得是ThreadLocal的继承类,比如例子中的MyThreadLocal,
     * 因为ThreadLocal本来被Common Classloader加载,其生命周期与Tomcat容器一致。
     * ThreadLocal的继承类包括比较常见的NamedThreadLocal,注意不要踩坑。
     * 假如LeakingServlet所在的Web应用启动,MyThreadLocal类也会被Webapp Classloader加载,
     * 如果此时web应用下线,而线程的生命周期未结束(比如为LeakingServlet提供服务的线程是一个线程池中的线程),
     * 那会导致myThreadLocal的实例仍然被这个线程引用,而不能被GC,期初看来这个带来的问题也不大,
     * 因为myThreadLocal所引用的对象占用的内存空间不太多,
     * 问题在于myThreadLocal间接持有加载web应用的webapp classloader的引用(通过myThreadLocal.getClass().getClassLoader()可以引用到),
     * 而加载web应用的webapp classloader有持有它加载的所有类的引用,这就引起了Classloader泄露,它泄露的内存就非常可观了
     */
}
